package com.clear.honghefinance.biz.modules.assist_calculate.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.clear.honghefinance.biz.modules.system.member.domain.vo.AdminDTO;
import com.clear.honghefinance.biz.modules.assist_calculate.converter.AssistCalculateCategoryConverter;
import com.clear.honghefinance.biz.modules.assist_calculate.domain.dto.CreateAssistCalculateCategoryDTO;
import com.clear.honghefinance.biz.modules.assist_calculate.domain.dto.DeleteAssistCalculateCategoryDTO;
import com.clear.honghefinance.biz.modules.assist_calculate.domain.dto.UpdateAssistCalculateCategoryDTO;
import com.clear.honghefinance.biz.modules.assist_calculate.domain.entity.AssistCalculateCate;
import com.clear.honghefinance.biz.modules.assist_calculate.domain.vo.GetAssistCalculateCategoryDetailVO;
import com.clear.honghefinance.biz.modules.assist_calculate.domain.vo.ListAssistCalculateCategoryVO;
import com.clear.honghefinance.biz.modules.assist_calculate.enums.AssistCalculateCategoryCodeEnum;
import com.clear.honghefinance.biz.modules.assist_calculate.enums.AssistCalculateCategoryLevelEnum;
import com.clear.honghefinance.biz.modules.assist_calculate.mapper.AssistCalculateCateMapper;
import com.clear.honghefinance.biz.modules.assist_calculate.service.IAssistCalculateCateService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.clear.honghefinance.common.exception.BizException;
import com.clear.honghefinance.common.service.TokenService;
import com.clear.honghefinance.common.util.DateUtil;
import com.google.common.reflect.TypeToken;
import com.google.gson.Gson;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.List;
import java.util.Objects;

/**
 * <p>
 * 辅助核算类别 服务实现类
 * </p>
 *
 * @author 程序员clear
 * @since 2024-08-23
 */
@Service
@Slf4j
public class AssistCalculateCateServiceImpl extends ServiceImpl<AssistCalculateCateMapper, AssistCalculateCate> implements IAssistCalculateCateService {

    @Resource
    private TokenService<AdminDTO> tokenService;

    /**
     * 创建辅助核算类别
     *
     * @param dto
     * @return
     */
    @Override
    public boolean create(CreateAssistCalculateCategoryDTO dto) {
        if (log.isInfoEnabled()) {
            log.info("创建辅助核算类别中，入参：{}", JSON.toJSONString(dto));
        }
        try {
            AssistCalculateCate assistCalculateCate = AssistCalculateCategoryConverter.INSTANCE.convertDTOToAssistCalculateCategoryEntity(dto);
            assistCalculateCate.setCode(AssistCalculateCategoryCodeEnum.CUSTOM.getCode());
            assistCalculateCate.setLevel(AssistCalculateCategoryLevelEnum.CUSTOM.getCode());
            assistCalculateCate.setTenantId(tokenService.getThreadLocalTenantId());
            assistCalculateCate.setMemberId(tokenService.getThreadLocalUserId());
            assistCalculateCate.setUpdateMemberId(tokenService.getThreadLocalUserId());
            assistCalculateCate.initDefault();
            if (Objects.nonNull(dto.getCustomerColumnConfigList())) {
                assistCalculateCate.setCustomerColumn(new Gson().toJson(dto.getCustomerColumnConfigList()));
            }
            if (this.save(assistCalculateCate)) {
                return true;
            } else {
                if (log.isInfoEnabled()) {
                    log.info("创建辅助核算类别异常，入参：{}", JSON.toJSONString(dto));
                }
                throw new BizException("创建辅助核算类别失败");
            }
        } catch (Exception e) {
            log.error("创建辅助核算类别异常 {}", e.getMessage(), e);
            throw new BizException("创建辅助核算类别失败");
        }
    }

    /**
     * 修改辅助核算类别
     *
     * @param dto
     * @return
     */
    @Override
    public boolean update(UpdateAssistCalculateCategoryDTO dto) {
        if (log.isInfoEnabled()) {
            log.info("编辑辅助核算类别中，入参：{}", JSON.toJSONString(dto));
        }
        AssistCalculateCate assistCalculateCate = this.getByCategoryId(dto.getId());
        if (assistCalculateCate == null) {
            throw new BizException("辅助核算类别不存在");
        }
        // 辅助核算类别已存在，不能重复
        if (Objects.nonNull(assistCalculateCate) && !Objects.equals(dto.getId(), assistCalculateCate.getId())) {
            throw new BizException("辅助核算类别已存在");
        }
        try {
            AssistCalculateCate calculateCate = AssistCalculateCategoryConverter.INSTANCE.convertDTOToAssistCalculateCategoryEntity(dto);
            calculateCate.setUpdateMemberId(tokenService.getThreadLocalUserId());
            calculateCate.setUpdateTime(DateUtil.getSystemTime());
            if (Objects.nonNull(dto.getCustomerColumnConfigList())) {
                calculateCate.setCustomerColumn(new Gson().toJson(dto.getCustomerColumnConfigList()));
            }

            LambdaUpdateWrapper<AssistCalculateCate> lambdaUpdateWrapper = Wrappers.<AssistCalculateCate>lambdaUpdate()
                    .eq(AssistCalculateCate::getId, dto.getId())
                    .eq(AssistCalculateCate::getLevel, AssistCalculateCategoryLevelEnum.CUSTOM.getCode())
                    // 只能修改当前租户下的辅助核算类别
                    .eq(AssistCalculateCate::getTenantId, tokenService.getThreadLocalTenantId())
                    .eq(AssistCalculateCate::getDelFlag, false);

            if (!this.update(calculateCate, lambdaUpdateWrapper)) {
                throw new BizException("修改辅助核算类别失败");
            }
            return true;
        } catch (Exception e) {
            log.error("编辑辅助核算类别异常 {}", e.getMessage(), e);
            throw new BizException("修改辅助核算类别失败");
        }
    }


    /**
     * 删除辅助核算类别
     *
     * @param dto
     * @return
     */
    @Override
    public boolean delete(DeleteAssistCalculateCategoryDTO dto) {
        if (log.isInfoEnabled()) {
            log.info("删除辅助核算类别中，入参：{}", JSON.toJSONString(dto));
        }
        AssistCalculateCate assistCalculateCate = this.getByCategoryId(dto.getId());
        if (assistCalculateCate == null) {
            throw new BizException("辅助核算类别不存在");
        }
        if (assistCalculateCate.getUseCount() > 0) {
            throw new BizException("该辅助核算下面已经有辅助核算数据不能删除");
        }
        try {
            LambdaUpdateWrapper<AssistCalculateCate> lambdaUpdateWrapper = Wrappers.<AssistCalculateCate>lambdaUpdate()
                    .eq(AssistCalculateCate::getId, dto.getId())
                    .eq(AssistCalculateCate::getLevel, AssistCalculateCategoryLevelEnum.CUSTOM.getCode())
                    // 目前只能删除自己的辅助核算类别
                    .eq(AssistCalculateCate::getTenantId, tokenService.getThreadLocalTenantId())
                    // 只能删除未使用的辅助核算类别
                    .eq(AssistCalculateCate::getUseCount, 0)
                    // 只能删除未禁用的辅助核算类别
                    .eq(AssistCalculateCate::getDelFlag, false)
                    .set(AssistCalculateCate::getDelFlag, true)
                    .set(AssistCalculateCate::getUpdateMemberId, tokenService.getThreadLocalUserId())
                    .set(AssistCalculateCate::getUpdateTime, DateUtil.getSystemTime());

            if (this.update(lambdaUpdateWrapper)) {
                return true;
            } else {
                if (log.isInfoEnabled()) {
                    log.info("删除辅助核算类别异常，入参：{}", JSON.toJSONString(dto));
                }
                throw new BizException("删除辅助核算类别失败");
            }
        } catch (Exception e) {
            log.error("删除辅助核算类别异常 {}", e.getMessage(), e);
            throw new BizException("删除辅助核算类别失败");
        }
    }

    /**
     * 查询辅助核算类别列表
     *
     * @return
     */
    @Override
    public List<ListAssistCalculateCategoryVO> listAll() {
        log.info("查看辅助核算类别列表中");
        try {
            LambdaQueryWrapper<AssistCalculateCate> lambdaQueryWrapper = Wrappers.<AssistCalculateCate>lambdaQuery()
                    .eq(AssistCalculateCate::getDelFlag, false)
                    // 只能查到当前租户的辅助核算类别
                    .eq(AssistCalculateCate::getTenantId, tokenService.getThreadLocalTenantId())
                    // 根据编码升序
                    .orderByAsc(AssistCalculateCate::getLevel)
                    .orderByAsc(AssistCalculateCate::getSort)
                    .orderByAsc(AssistCalculateCate::getUpdateTime);

            List<AssistCalculateCate> list = this.list(lambdaQueryWrapper);
            return AssistCalculateCategoryConverter.INSTANCE.convertAssistCalculateCategoryEntityToListAssistCalculateCategoryVO(list);

        } catch (Exception e) {
            log.error("查询辅助核算类别异常 {}", e.getMessage(), e);
            throw new BizException("查询辅助核算类别异常");
        }
    }

    /**
     * 获取辅助核算类别详情
     *
     * @param id
     * @return
     */
    @Override
    public GetAssistCalculateCategoryDetailVO getDetailById(long id) {
        log.info("查看辅助核算类别明细中，入参：{}", id);
        try {
            LambdaQueryWrapper<AssistCalculateCate> lambdaQueryWrapper = Wrappers.<AssistCalculateCate>lambdaQuery()
                    .eq(AssistCalculateCate::getId, id)
                    .eq(AssistCalculateCate::getDelFlag, false)
                    // 只能查到当前租户的辅助核算类别
                    .eq(AssistCalculateCate::getTenantId, tokenService.getThreadLocalTenantId());
            AssistCalculateCate assistCalculateCate = this.getOne(lambdaQueryWrapper);
            if (Objects.isNull(assistCalculateCate)) {
                throw new BizException("辅助核算类别不存在");
            }
            GetAssistCalculateCategoryDetailVO vo = AssistCalculateCategoryConverter.INSTANCE
                    .convertAssistCalculateCategoryEntityToGetAssistCalculateCategoryDetailVO(assistCalculateCate);
            vo.setCustomerColumnConfigList(new Gson().fromJson(assistCalculateCate.getCustomerColumn(),
                            new TypeToken<List<GetAssistCalculateCategoryDetailVO.CustomerColumnConfig>>() {
                            }.getType()
                    )
            );
            return vo;
        } catch (Exception e) {
            log.error("查看辅助核算类别明细异常 {}", e.getMessage(), e);
            throw new BizException("查看辅助核算类别明细异常");
        }
    }


    /**
     * 根据id获取辅助核算类别
     *
     * @param id
     * @return
     */
    @Override
    public AssistCalculateCate getByCategoryId(long id) {
        return this.getOne(Wrappers.<AssistCalculateCate>lambdaQuery()
                .eq(AssistCalculateCate::getId, id)
                .eq(AssistCalculateCate::getDelFlag, false)
                .eq(AssistCalculateCate::getTenantId, tokenService.getThreadLocalTenantId())
        );
    }

    /**
     * 增加辅助核算类别使用计数
     *
     * @param id
     * @param count
     * @return
     */
    @Override
    public boolean addUseCount(long id, int count) {
        log.info("增加辅助核算类别使用计数中，入参：id={}，count={} ", id, count);
        try {
            boolean updateFlag = this.update(Wrappers.<AssistCalculateCate>lambdaUpdate()
                    .eq(AssistCalculateCate::getId, id)
                    .setSql("use_count = use_count + #{count}")
            );
            if (updateFlag) {
                return true;
            }
            throw new BizException("增加辅助核算类别使用计数异常");
        } catch (Exception e) {
            log.error("增加辅助核算类别使用计数异常 {}", e.getMessage(), e);
            throw new BizException("增加辅助核算类别使用计数异常");
        }
    }

    /**
     * 减少辅助核算类别使用计数
     *
     * @param id
     * @param count
     * @return
     */
    @Override
    public boolean deductUseCount(long id, int count) {
        log.info("减少辅助核算类别使用计数中，入参：id={}，count={} ", id, count);
        try {
            boolean updateFlag = this.update(Wrappers.<AssistCalculateCate>lambdaUpdate()
                    .eq(AssistCalculateCate::getId, id)
                    .setSql("use_count = use_count - #{count}")
            );
            if (updateFlag) {
                return true;
            }
            throw new BizException("减少辅助核算类别使用计数异常");
        } catch (Exception e) {
            log.error("减少辅助核算类别使用计数异常 {}", e.getMessage(), e);
            throw new BizException("减少辅助核算类别使用计数异常");
        }
    }
}
